<% ASP на блюдечке %>. Часть 12

Чат своими силами (версия 2)

Рубен Садоян

Введение

Что же такое чат?

Постановка задачи

Структура приложения

Что нам понадобится

Создание и подготовка базы данных

   Универсальный набор функций (файл utils.asp)

   Вход в чат (файл Entrance.asp)

   Вход в чат впервые

   Mодуль добавления новых пользователей в систему (AddUser.asp)

   Просмотр списка сообщений чата (файл Text.asp)

   Посылка сообщения в чат (файл Chat.asp)

   Показ псевдонимов (кто в чате) — файл Nicks.asp

   Немного об оформлении

   И еще об одной немаловажной проблеме…

Заключение

Введение

Как мы уже отмечали в предыдущих статьях настоящей серии, тема Интернет-общения актуальна, однако согласитесь, что созданная нами в части 9 настоящей статьи чат-система не лишена недостатков. Наиболее существенным из них является то, что система реализована на базе файловой системы сервера, что, с одной стороны, позволило нам вникнуть в подробности и детально изучить принципы и методы работы с файлами средствами ASP, а с другой — создать достаточно удобный чат-интерфейс, вполне приемлемый для организации общения ограниченного числа пользователей. Однако наверняка читатель заметит проблему, которую таит в себе такой подход, а именно: при возрастании числа пользователей такой системы (транзакционной нагрузки на сервер) обязательно возникнет ситуация, когда файловая система сервера не будет успевать обрабатывать запросы пользовательских страниц, что неизбежно приведет к остановке системы. Именно поэтому в настоящей статье мы продолжим обучение навыкам построения чат-систем и освоим процесс создания базо-основанной, а не файл-основанной  чат-системы.

Однако не будем забегать вперед, а попробуем формализовать всю задачу с нуля, с тем чтобы представить себе ее решение максимально детально.

Итак, настоящая статья адресована тем читателям, которые хотели бы самостоятельно разработать с нуля собственную чат-систему.

В начало В начало

Что же такое чат?

Настоятельно рекомендую вам задаться этим вопросом, прежде чем продолжать чтение данной статьи.

Как известно, чат — это некая область окна браузера, в которой пользователи могут просматривать текстовые сообщения других пользователей и добавлять свои. Поток сообщений общий, поэтому сообщение, введенное любым пользователем, доступно для всех (хотя существуют чат-системы с возможностью «уединенной» беседы, то есть когда часть сообщений адресована какому-то конкретному пользователю и для остальных пользователей недоступна).

Таким образом, чат представляет собой одномерный поток текстовых сообщений (в отличие от форума, который является двухмерным потоком текстовых сообщений).

Теперь, когда картина нам в общем ясна, предлагаю разобраться с функционалом чат-систем, который, как правило, состоит из следующих функциональных компонентов:

Этот список можно продолжать, однако, чтобы не усложнять изложение материала, мы не будем этого делать в настоящей статье, а ограничимся лишь наиболее типичными требованиями.

В начало В начало

Постановка задачи

С программной точки зрения чат-система должна представлять собой совокупность модулей, каждый из которых предназначен для решения одной из вышеизложенных задач. Таким образом, в состав наиболее типичной чат-системы входят:

  1. Модуль идентификации пользователей.
  2. Модуль представления потока сообщений всех пользователей.
  3. Модуль представления имен (псевдонимов) всех подключенных пользователей.
  4. Модуль формирования и ввода новых сообщений.
В начало В начало

Структура приложения

Однако прежде чем приступать к созданию базо-основанного чата, давайте представим себе, каким же образом будет осуществляться обмен сообщениями — ведь в качестве носителя данных у нас теперь выступают не файлы на жестком диске сервера, а база данных. Да очень просто: все текстовые сообщения, предварительно обрамленные в необходимые HTML-тэги форматирования, будут «складываться» в определенную таблицу базы данных, после чего будет генерироваться страница на основе этой таблицы, которая будет доступна всем пользователям нашего чата. Аналогичные действия необходимо проделать и со страницей псевдонимов, которая, в свою очередь, будет генерироваться на основании таблицы пользователей.

В начало В начало

Что нам понадобится

Конечно же, предполагается, что читатель знаком с основами ASP- и SQL-программирования (первых частей настоящей статьи для этого будет вполне достаточно). Кроме того, нам потребуется Microsoft SQL Server 7.0 или 2000, какой-нибудь HTML- или текстовый редактор (рекомендую использовать Macromedia Dreamweaver UltraDev 4.0) и немного терпения.

В начало В начало

Создание и подготовка базы данных

Создадим две таблицы: таблицу пользователей (ChatUsers) и таблицу сообщений (Chat). Представим себе их взаимосвязь так, как показано на рисунке.

Ключевыми здесь являются столбцы UserID. Их взаимосвязь, по сути, отражает взаимосвязь сообщений и их авторов. Теперь, когда база данных готова, можно переходить к созданию самого форума.

Однако прежде следует уяснить вопрос, каким именно образом будет отслеживаться состояние пользователей, находящихся в режиме онлайн? Для этого в таблице пользователей необходимо предусмотреть соответствующую галочку (поле). Таким образом, выполняя соответствующий запрос к таблице пользователей, можно будет выяснить, кто из пользователей находится в режиме онлайн.

В начало В начало

Универсальный набор функций (файл utils.asp)

Прежде чем приступить непосредственно к разработке нашего чата, вынесем все многократно используемые типовые функции в один файл, который впоследствии по мере необходимости будем «включать» в разрабатываемые странички. Разберемся, что нам для этого понадобится. Прежде всего это функции соединения и закрытия соединения с базой данных:

<% @ LANGUAGE="VBSCRIPT" %>  
<% Option Explicit %>  
<!--#include file="cdovbs.inc"-->  
   
<%  
 option explicit  
 Response.Buffer = true  
   
 '***** Строим строку соединения с базой данных ***************************  
 dim Dsn, Conn, Rs, sSQL  
Dsn = "DSN=Chat; UID=sa;PWD=;database=Chat"  
   
 '**** Подсоединяемся к базе данных форума ********************************  
   
 Sub Connect()  
  set conn = server.createobject("adodb.connection")  
  set rs = server.createobject("adodb.recordset")  
  conn.open Dsn  
 End Sub  
   
 '**** Закрываем соединение с базой данных форума *************************  
   
 Sub Close()  
  Rs.close  
  set Rs = nothing  
  Conn.close  
  set Conn = nothing  
 End Sub  
%> 
В начало В начало

Вход в чат (файл Entrance.asp)

Главная страница чата предназначена для выбора пользователем имени-псевдонима и пароля, указания им предпочтительного цвета имени, а также для нескольких настроек: количества одновременно отображаемых сообщений и времени обновления текстовой страницы в секундах.

<!--#include file="utils.asp"-->
<SCRIPT LANGUAGE = VBScript RUNAT=Server>
 <!-- Metadata type="typelib" File="c:\program files\common files\system\ado\msado15.dll" -->
</SCRIPT>
<%
 Dim IName, Passwd, Msg, CurUser, Odd, NameNum, db, IsError, TextStr, Str
 Iname  = Request.Form("nickname")
 Passwd = Request.Form("passwd")
 If IName = "" Then
   msg = "Вы не ввели логин пользователя!"
   IsError = True             
 Else 
   If Passwd = "" Then
     msg = "Вы не ввели пароль пользователя!"
     IsError = True         
   End If
  
   If InStr(IName,"<") < 1 Then 
     Call Connect
     sSQL = "SELECT * FROM ChatUsers WHERE UserNickName = '" & Iname & "' AND UserPassword = '" & Passwd & "'"
     Rs.open sSQL, Conn
                    
     If rs.Eof Then
        IsError = True         
        msg = "<font color='red'>Вы ошиблись при вводе имени пользователя и/или пароля.</font>"
     End If
                    
     If Not IsError Then
       IsError = False
       Session("UserID") = Rs.Fields("UserID").value
       Session("UserName") = Iname
       Session("UserColor") = Request("user_color")
       Session("RefreshTime") = Request("RefreshTime")
       Session("LNum") = Request("LNum")
 
       TextStr = "<table><tr><td><B><font color='" & Session("UserColor") &"'>" & _
                       Session("UserName") & "</font></B>" &_
                      " : " & "вошел в чат - " & date & " " & time & "</td></tr></table>"
 
       Call Close()
       Call Connect()
 
       sSQL = "SELECT * FROM Chat"
       RS.Open sSQL, Conn, 3, adLockOptimistic
 
       rs.AddNew
       rs("UserID") = 0
       rs("DateSaid") = Now()
       rs("Said") = TextStr
       rs.Update
 
       Call Close()
       Call Connect()
       
       sSQL = "UPDATE ChatUsers Set IsOnLine = 1, UserColor = '" & Session("UserColor") &_
             "' WHERE UserNickName = '" & Iname & "' AND UserPassword = '" & Passwd & "'"
       Conn.Execute(sSQL)
       Conn.close
       set Conn = nothing
 
       Response.Redirect("MainFS.asp")                   
     End If
 
     IsError = false
     Call Close
   End If 
 End If
%>
 
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</head>
 
<body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF">
<BR><BR><BR>
 
<center>
<font color="#000000" size=+2>Добро пожаловать в Чат</font>
</center>
 
<BR>
<center>
<p>Сейчас в чате:</p>
 
<table align= "center" width= 400 border = 0>
<tr><td align= "center">
<%
  CurUser = 0
  Odd = 0
  NameNum = 0
 
  Call Connect
  sSQL = "SELECT * FROM ChatUsers WHERE IsOnline = 1"
 
  Rs.open sSQL, Conn
 
  Do While Not rs.EOF
    If Odd = 0 Then
      If NameNum = 10 Then 
        Response.Write "</td></tr><tr><td align= 'center'>"
        NameNum = 0
      End If
      Str = Rs.Fields("UserNickName").value
      If Str <> "" Then
        Response.Write "[" & Str & "]&nbsp;"
        Odd = 1
        CurUser = CurUser + 1
        NameNum = NameNum + 1
      End If
   Else
     Odd = 0
      Rs.MoveNext
    End If
  Loop         
 
  If CurUser = 0 Then
    Response.Write "нет пользователей"
  Else
    Response.Write "</td></tr><tr><td align= 'center'>Всего " & CurUser
  End If
 
 Call Close
%>
</td></tr></table>
<br>
 
<Form name="Nickname" method="post" action="Entrance.asp">
 
 <table width= 400 border = 1>
 
  <tr>
   <td>Ваш псевдоним:</td>
   <td><input type=text name="nickname" value="" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td>
  </tr>
 
  <tr>
   <td>Ваш пароль:</td>
   <td><input type=password name="passwd" value="" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td>
  </tr>
 
 
  <tr>
   <td></td><td><a href = "Newuser.asp">Новый пользователь?</a></td>
  </tr>
 
 
  <tr>
   <td valign="top">Ваш цвет:</td>
   <td>
   <FONT FACE="arial, verdana, helvetica" SIZE="2">
…
 
Группа переключателей (радиокнопок) для выбора цвета.
 
…
   </FONT>
   </td>
  </tr>

   <tr>
   <TD>Обновление чата:</TD>
   <TD><SELECT NAME="RefreshTime" style="font: 8pt 'Verdana'; background-color: #FCFBE8;">

    <OPTION VALUE="5">5
    <OPTION VALUE="10"Selected>10
    <OPTION VALUE="15">15

    <OPTION VALUE="20">20

    <OPTION VALUE="30">30
    <OPTION VALUE="60">60

   </SELECT>&nbsp;секунд
   </TD>
  </tr>


   <tr>

  <td>Просматриваемых сообщений:</td>
  <td><INPUT TYPE="text" NAME="LNum" VALUE="30" SIZE="2" MAXLENGTH="2" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td>
  </tr>
 


 </table>
<br>

<input type=submit name="okbtn" value="Войти" 

</Form>

 <BR><H6><%=msg%><br>Использование HTML-тэгов недопустимо!</h6><BR>
</center>


 </body>

</html>
В начало В начало

Вход в чат впервые

Далее система попытается найти указанного пользователя в таблице пользователей, и если ей это не удастся, то пользователь не будет допущен в чат. Для «вновь прибывших» пользователей следует предусмотреть механизм регистрации в системе, форму регистрации с проверкой введенных значений на допустимые диапазоны и типы, а также модуль добавления новых пользователей в систему:

Форма регистрации для новых пользователей (файл NewUser.asp):

<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
 <title>чат (регистрационная форма)</title>
 <SCRIPT TYPE="text/javascript" SRC="script.js">
 <!-- // displays only if script file not found
  document.write ("JavaScript library not found.");
 //-->
 </SCRIPT>
 <SCRIPT TYPE="text/javascript">
 <!--
 function checkMe() {
  var ok;  
 with (document.EOForm){
  if ( isBlank(Nick, 'Введите Ваш псевдоним.')) return false;
  if ( isBlank(Name, 'Введите Ваше имя.')) return false;
  if ( !PasswordCheck(Password, repPassword)) return false;
  if ( isBlank(Email,'Введите адрес электронной почты')) return false;
  if (!isEmail(Email,'Введите адрес электронной почты в правильном формате (например, somebody@domain.ru)'))                return false;
  if (!isIntegerValue(UIN,'Введите правильно Ваш номер ICQ.')) return false;
  }
  return true;
 }
 //-->
 
 </SCRIPT>
 </head>
 <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF">
 <table align = "center" width="570" border="0" cellspacing="0" cellpadding="0"><tr><td>
 <div align="center">
 <p><b>Пожалуйста, заполните эту форму для получения доступа в чат:</b></p>
 <Form name = "EOForm" Method="get" Action = "AddUser.asp" onSubmit="return checkMe();">
 <table width="470" border="0" cellspacing="3" cellpadding="0">
 
 <tr><td>Ваш псевдоним (nickname) (*):</td>
 <td><Input Type="text" Name="Nick" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td>
 
 </tr>
 <tr><td>Ваше имя(*):</td>
 <td><Input Type="text" Name="Name" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td>
 </tr>
 
 <tr><td>Ваш пароль(*):</td>
 <td><Input Type="password" Name="Password" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td>
 </tr>  
<tr><td>Повторите пароль(*):</td>
 <td><Input Type="password" Name="repPassword" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td>
 </tr>
 
 <tr>
 <td>Ваш электронный адрес(*):</td>
 <td><Input Type="text" Name="Email" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td>
 </tr>  
<tr>
 <td>Ваш URL:</td>
 <td><Input Type="text" Name="URL" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></Input></td>
 </tr>  
<tr>
 <td>Ваш номер ICQ:</td>
 <td><Input Type="text" Name="UIN" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></Input></td>
 </tr>  
<tr>
 <td>Другая информация:<BR></td>
 <td><textarea Type="text" Name="Info" cols="29" rows="5" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></textarea></td>
 </tr>  
</table>
 <br>
 <Input Type="submit" style="WIDTH: 150px" Value="Подтверждаю">
 <input type="reset" style="WIDTH: 150px" value="Очистить" name="Reset">
 </form>
 </div>
 </td></tr>
 </table>
 </body>
 </html>  

Проверка корректности введенных пользователем значений полей формы реализуется путем вызова ряда JavaScript-функций проверки из библиотеки script.js. Однако мы не будем останавливаться на всех этих функциях подробно, так как мы делали это в одной из предыдущих статей настоящей серии.

В начало В начало

Mодуль добавления новых пользователей в систему (AddUser.asp)

<!--#include file="utils.asp"-->  
   
<SCRIPT LANGUAGE = VBScript RUNAT=Server>  
 <!-- Metadata type="typelib" File="c:\program files\common files\system\ado\msado15.dll" -->  
</SCRIPT>  
   
<%   
  Call Connect()  
  sSQL = "SELECT * FROM ChatUsers"  
  RS.Open sSQL, Conn, 3, adLockOptimistic  
   
  rs.AddNew  
   
  rs("UserNickName") = request("Nick")  
  rs("UserName") = request("Name")  
  rs("UserPassword") = request("Password")  
  rs("UserMail") = request("EMail")  
  rs("UserURL") = request("URL")  
  rs("UserUIN") = request("UIN")  
  rs("UserInfo") = request("Info")  
  rs("IsOnLine") = False  
   
  rs.Update  
  Call Close()  
   
  Response.Redirect "Entrance.asp"  
%>